tutorial_tests = '\nLet\'s try a simple generator:\n\n >>> def f():\n ... yield 1\n ... yield 2\n\n >>> for i in f():\n ... print i\n 1\n 2\n >>> g = f()\n >>> g.next()\n 1\n >>> g.next()\n 2\n\n"Falling off the end" stops the generator:\n\n >>> g.next()\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n File "<stdin>", line 2, in g\n StopIteration\n\n"return" also stops the generator:\n\n >>> def f():\n ... yield 1\n ... return\n ... yield 2 # never reached\n ...\n >>> g = f()\n >>> g.next()\n 1\n >>> g.next()\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n File "<stdin>", line 3, in f\n StopIteration\n >>> g.next() # once stopped, can\'t be resumed\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n StopIteration\n\n"raise StopIteration" stops the generator too:\n\n >>> def f():\n ... yield 1\n ... raise StopIteration\n ... yield 2 # never reached\n ...\n >>> g = f()\n >>> g.next()\n 1\n >>> g.next()\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n StopIteration\n >>> g.next()\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n StopIteration\n\nHowever, they are not exactly equivalent:\n\n >>> def g1():\n ... try:\n ... return\n ... except:\n ... yield 1\n ...\n >>> list(g1())\n []\n\n >>> def g2():\n ... try:\n ... raise StopIteration\n ... except:\n ... yield 42\n >>> print list(g2())\n [42]\n\nThis may be surprising at first:\n\n >>> def g3():\n ... try:\n ... return\n ... finally:\n ... yield 1\n ...\n >>> list(g3())\n [1]\n\nLet\'s create an alternate range() function implemented as a generator:\n\n >>> def yrange(n):\n ... for i in range(n):\n ... yield i\n ...\n >>> list(yrange(5))\n [0, 1, 2, 3, 4]\n\nGenerators always return to the most recent caller:\n\n >>> def creator():\n ... r = yrange(5)\n ... print "creator", r.next()\n ... return r\n ...\n >>> def caller():\n ... r = creator()\n ... for i in r:\n ... print "caller", i\n ...\n >>> caller()\n creator 0\n caller 1\n caller 2\n caller 3\n caller 4\n\nGenerators can call other generators:\n\n >>> def zrange(n):\n ... for i in yrange(n):\n ... yield i\n ...\n >>> list(zrange(5))\n [0, 1, 2, 3, 4]\n\n'
pep_tests = '\n\nSpecification: Yield\n\n Restriction: A generator cannot be resumed while it is actively\n running:\n\n >>> def g():\n ... i = me.next()\n ... yield i\n >>> me = g()\n >>> me.next()\n Traceback (most recent call last):\n ...\n File "<string>", line 2, in g\n ValueError: generator already executing\n\nSpecification: Return\n\n Note that return isn\'t always equivalent to raising StopIteration: the\n difference lies in how enclosing try/except constructs are treated.\n For example,\n\n >>> def f1():\n ... try:\n ... return\n ... except:\n ... yield 1\n >>> print list(f1())\n []\n\n because, as in any function, return simply exits, but\n\n >>> def f2():\n ... try:\n ... raise StopIteration\n ... except:\n ... yield 42\n >>> print list(f2())\n [42]\n\n because StopIteration is captured by a bare "except", as is any\n exception.\n\nSpecification: Generators and Exception Propagation\n\n >>> def f():\n ... return 1//0\n >>> def g():\n ... yield f() # the zero division exception propagates\n ... yield 42 # and we\'ll never get here\n >>> k = g()\n >>> k.next()\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n File "<stdin>", line 2, in g\n File "<stdin>", line 2, in f\n ZeroDivisionError: integer division or modulo by zero\n >>> k.next() # and the generator cannot be resumed\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n StopIteration\n >>>\n\nSpecification: Try/Except/Finally\n\n >>> def f():\n ... try:\n ... yield 1\n ... try:\n ... yield 2\n ... 1//0\n ... yield 3 # never get here\n ... except ZeroDivisionError:\n ... yield 4\n ... yield 5\n ... raise\n ... except:\n ... yield 6\n ... yield 7 # the "raise" above stops this\n ... except:\n ... yield 8\n ... yield 9\n ... try:\n ... x = 12\n ... finally:\n ... yield 10\n ... yield 11\n >>> print list(f())\n [1, 2, 4, 5, 8, 9, 10, 11]\n >>>\n\nGuido\'s binary tree example.\n\n >>> # A binary tree class.\n >>> class Tree:\n ...\n ... def __init__(self, label, left=None, right=None):\n ... self.label = label\n ... self.left = left\n ... self.right = right\n ...\n ... def __repr__(self, level=0, indent=" "):\n ... s = level*indent + repr(self.label)\n ... if self.left:\n ... s = s + "\\n" + self.left.__repr__(level+1, indent)\n ... if self.right:\n ... s = s + "\\n" + self.right.__repr__(level+1, indent)\n ... return s\n ...\n ... def __iter__(self):\n ... return inorder(self)\n\n >>> # Create a Tree from a list.\n >>> def tree(list):\n ... n = len(list)\n ... if n == 0:\n ... return []\n ... i = n // 2\n ... return Tree(list[i], tree(list[:i]), tree(list[i+1:]))\n\n >>> # Show it off: create a tree.\n >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")\n\n >>> # A recursive generator that generates Tree labels in in-order.\n >>> def inorder(t):\n ... if t:\n ... for x in inorder(t.left):\n ... yield x\n ... yield t.label\n ... for x in inorder(t.right):\n ... yield x\n\n >>> # Show it off: create a tree.\n >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")\n >>> # Print the nodes of the tree in in-order.\n >>> for x in t:\n ... print x,\n A B C D E F G H I J K L M N O P Q R S T U V W X Y Z\n\n >>> # A non-recursive generator.\n >>> def inorder(node):\n ... stack = []\n ... while node:\n ... while node.left:\n ... stack.append(node)\n ... node = node.left\n ... yield node.label\n ... while not node.right:\n ... try:\n ... node = stack.pop()\n ... except IndexError:\n ... return\n ... yield node.label\n ... node = node.right\n\n >>> # Exercise the non-recursive generator.\n >>> for x in t:\n ... print x,\n A B C D E F G H I J K L M N O P Q R S T U V W X Y Z\n\n'
email_tests = '\n\nThe difference between yielding None and returning it.\n\n>>> def g():\n... for i in range(3):\n... yield None\n... yield None\n... return\n>>> list(g())\n[None, None, None, None]\n\nEnsure that explicitly raising StopIteration acts like any other exception\nin try/except, not like a return.\n\n>>> def g():\n... yield 1\n... try:\n... raise StopIteration\n... except:\n... yield 2\n... yield 3\n>>> list(g())\n[1, 2, 3]\n\nNext one was posted to c.l.py.\n\n>>> def gcomb(x, k):\n... "Generate all combinations of k elements from list x."\n...\n... if k > len(x):\n... return\n... if k == 0:\n... yield []\n... else:\n... first, rest = x[0], x[1:]\n... # A combination does or doesn\'t contain first.\n... # If it does, the remainder is a k-1 comb of rest.\n... for c in gcomb(rest, k-1):\n... c.insert(0, first)\n... yield c\n... # If it doesn\'t contain first, it\'s a k comb of rest.\n... for c in gcomb(rest, k):\n... yield c\n\n>>> seq = range(1, 5)\n>>> for k in range(len(seq) + 2):\n... print "%d-combs of %s:" % (k, seq)\n... for c in gcomb(seq, k):\n... print " ", c\n0-combs of [1, 2, 3, 4]:\n []\n1-combs of [1, 2, 3, 4]:\n [1]\n [2]\n [3]\n [4]\n2-combs of [1, 2, 3, 4]:\n [1, 2]\n [1, 3]\n [1, 4]\n [2, 3]\n [2, 4]\n [3, 4]\n3-combs of [1, 2, 3, 4]:\n [1, 2, 3]\n [1, 2, 4]\n [1, 3, 4]\n [2, 3, 4]\n4-combs of [1, 2, 3, 4]:\n [1, 2, 3, 4]\n5-combs of [1, 2, 3, 4]:\n\nFrom the Iterators list, about the types of these things.\n\n>>> def g():\n... yield 1\n...\n>>> type(g)\n<type \'function\'>\n>>> i = g()\n>>> type(i)\n<type \'generator\'>\n>>> [s for s in dir(i) if not s.startswith(\'_\')]\n[\'gi_frame\', \'gi_running\', \'next\']\n>>> print i.next.__doc__\nx.next() -> the next value, or raise StopIteration\n>>> iter(i) is i\nTrue\n>>> import types\n>>> isinstance(i, types.GeneratorType)\nTrue\n\nAnd more, added later.\n\n>>> i.gi_running\n0\n>>> type(i.gi_frame)\n<type \'frame\'>\n>>> i.gi_running = 42\nTraceback (most recent call last):\n ...\nTypeError: readonly attribute\n>>> def g():\n... yield me.gi_running\n>>> me = g()\n>>> me.gi_running\n0\n>>> me.next()\n1\n>>> me.gi_running\n0\n\nA clever union-find implementation from c.l.py, due to David Eppstein.\nSent: Friday, June 29, 2001 12:16 PM\nTo: python-list@python.org\nSubject: Re: PEP 255: Simple Generators\n\n>>> class disjointSet:\n... def __init__(self, name):\n... self.name = name\n... self.parent = None\n... self.generator = self.generate()\n...\n... def generate(self):\n... while not self.parent:\n... yield self\n... for x in self.parent.generator:\n... yield x\n...\n... def find(self):\n... return self.generator.next()\n...\n... def union(self, parent):\n... if self.parent:\n... raise ValueError("Sorry, I\'m not a root!")\n... self.parent = parent\n...\n... def __str__(self):\n... return self.name\n\n>>> names = "ABCDEFGHIJKLM"\n>>> sets = [disjointSet(name) for name in names]\n>>> roots = sets[:]\n\n>>> import random\n>>> gen = random.WichmannHill(42)\n>>> while 1:\n... for s in sets:\n... print "%s->%s" % (s, s.find()),\n... print\n... if len(roots) > 1:\n... s1 = gen.choice(roots)\n... roots.remove(s1)\n... s2 = gen.choice(roots)\n... s1.union(s2)\n... print "merged", s1, "into", s2\n... else:\n... break\nA->A B->B C->C D->D E->E F->F G->G H->H I->I J->J K->K L->L M->M\nmerged D into G\nA->A B->B C->C D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M\nmerged C into F\nA->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->L M->M\nmerged L into A\nA->A B->B C->F D->G E->E F->F G->G H->H I->I J->J K->K L->A M->M\nmerged H into E\nA->A B->B C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M\nmerged B into E\nA->A B->E C->F D->G E->E F->F G->G H->E I->I J->J K->K L->A M->M\nmerged J into G\nA->A B->E C->F D->G E->E F->F G->G H->E I->I J->G K->K L->A M->M\nmerged E into G\nA->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->M\nmerged M into G\nA->A B->G C->F D->G E->G F->F G->G H->G I->I J->G K->K L->A M->G\nmerged I into K\nA->A B->G C->F D->G E->G F->F G->G H->G I->K J->G K->K L->A M->G\nmerged K into A\nA->A B->G C->F D->G E->G F->F G->G H->G I->A J->G K->A L->A M->G\nmerged F into A\nA->A B->G C->A D->G E->G F->A G->G H->G I->A J->G K->A L->A M->G\nmerged A into G\nA->G B->G C->G D->G E->G F->G G->G H->G I->G J->G K->G L->G M->G\n'
fun_tests = '\n\nBuild up to a recursive Sieve of Eratosthenes generator.\n\n>>> def firstn(g, n):\n... return [g.next() for i in range(n)]\n\n>>> def intsfrom(i):\n... while 1:\n... yield i\n... i += 1\n\n>>> firstn(intsfrom(5), 7)\n[5, 6, 7, 8, 9, 10, 11]\n\n>>> def exclude_multiples(n, ints):\n... for i in ints:\n... if i % n:\n... yield i\n\n>>> firstn(exclude_multiples(3, intsfrom(1)), 6)\n[1, 2, 4, 5, 7, 8]\n\n>>> def sieve(ints):\n... prime = ints.next()\n... yield prime\n... not_divisible_by_prime = exclude_multiples(prime, ints)\n... for p in sieve(not_divisible_by_prime):\n... yield p\n\n>>> primes = sieve(intsfrom(2))\n>>> firstn(primes, 20)\n[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]\n\n\nAnother famous problem: generate all integers of the form\n 2**i * 3**j * 5**k\nin increasing order, where i,j,k >= 0. Trickier than it may look at first!\nTry writing it without generators, and correctly, and without generating\n3 internal results for each result output.\n\n>>> def times(n, g):\n... for i in g:\n... yield n * i\n>>> firstn(times(10, intsfrom(1)), 10)\n[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]\n\n>>> def merge(g, h):\n... ng = g.next()\n... nh = h.next()\n... while 1:\n... if ng < nh:\n... yield ng\n... ng = g.next()\n... elif ng > nh:\n... yield nh\n... nh = h.next()\n... else:\n... yield ng\n... ng = g.next()\n... nh = h.next()\n\nThe following works, but is doing a whale of a lot of redundant work --\nit\'s not clear how to get the internal uses of m235 to share a single\ngenerator. Note that me_times2 (etc) each need to see every element in the\nresult sequence. So this is an example where lazy lists are more natural\n(you can look at the head of a lazy list any number of times).\n\n>>> def m235():\n... yield 1\n... me_times2 = times(2, m235())\n... me_times3 = times(3, m235())\n... me_times5 = times(5, m235())\n... for i in merge(merge(me_times2,\n... me_times3),\n... me_times5):\n... yield i\n\nDon\'t print "too many" of these -- the implementation above is extremely\ninefficient: each call of m235() leads to 3 recursive calls, and in\nturn each of those 3 more, and so on, and so on, until we\'ve descended\nenough levels to satisfy the print stmts. Very odd: when I printed 5\nlines of results below, this managed to screw up Win98\'s malloc in "the\nusual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting\naddress space, and it *looked* like a very slow leak.\n\n>>> result = m235()\n>>> for i in range(3):\n... print firstn(result, 15)\n[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]\n[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]\n[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]\n\nHeh. Here\'s one way to get a shared list, complete with an excruciating\nnamespace renaming trick. The *pretty* part is that the times() and merge()\nfunctions can be reused as-is, because they only assume their stream\narguments are iterable -- a LazyList is the same as a generator to times().\n\n>>> class LazyList:\n... def __init__(self, g):\n... self.sofar = []\n... self.fetch = g.next\n...\n... def __getitem__(self, i):\n... sofar, fetch = self.sofar, self.fetch\n... while i >= len(sofar):\n... sofar.append(fetch())\n... return sofar[i]\n\n>>> def m235():\n... yield 1\n... # Gack: m235 below actually refers to a LazyList.\n... me_times2 = times(2, m235)\n... me_times3 = times(3, m235)\n... me_times5 = times(5, m235)\n... for i in merge(merge(me_times2,\n... me_times3),\n... me_times5):\n... yield i\n\nPrint as many of these as you like -- *this* implementation is memory-\nefficient.\n\n>>> m235 = LazyList(m235())\n>>> for i in range(5):\n... print [m235[j] for j in range(15*i, 15*(i+1))]\n[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]\n[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]\n[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]\n[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]\n[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]\n\n\nYe olde Fibonacci generator, LazyList style.\n\n>>> def fibgen(a, b):\n...\n... def sum(g, h):\n... while 1:\n... yield g.next() + h.next()\n...\n... def tail(g):\n... g.next() # throw first away\n... for x in g:\n... yield x\n...\n... yield a\n... yield b\n... for s in sum(iter(fib),\n... tail(iter(fib))):\n... yield s\n\n>>> fib = LazyList(fibgen(1, 2))\n>>> firstn(iter(fib), 17)\n[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]\n'
syntax_tests = '\n\n>>> def f():\n... return 22\n... yield 1\nTraceback (most recent call last):\n ..\nSyntaxError: \'return\' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 2)\n\n>>> def f():\n... yield 1\n... return 22\nTraceback (most recent call last):\n ..\nSyntaxError: \'return\' with argument inside generator (<doctest test.test_generators.__test__.syntax[1]>, line 3)\n\n"return None" is not the same as "return" in a generator:\n\n>>> def f():\n... yield 1\n... return None\nTraceback (most recent call last):\n ..\nSyntaxError: \'return\' with argument inside generator (<doctest test.test_generators.__test__.syntax[2]>, line 3)\n\nThis one is fine:\n\n>>> def f():\n... yield 1\n... return\n\n>>> def f():\n... try:\n... yield 1\n... finally:\n... pass\nTraceback (most recent call last):\n ..\nSyntaxError: \'yield\' not allowed in a \'try\' block with a \'finally\' clause (<doctest test.test_generators.__test__.syntax[4]>, line 3)\n\n>>> def f():\n... try:\n... try:\n... 1//0\n... except ZeroDivisionError:\n... yield 666 # bad because *outer* try has finally\n... except:\n... pass\n... finally:\n... pass\nTraceback (most recent call last):\n ...\nSyntaxError: \'yield\' not allowed in a \'try\' block with a \'finally\' clause (<doctest test.test_generators.__test__.syntax[5]>, line 6)\n\nBut this is fine:\n\n>>> def f():\n... try:\n... try:\n... yield 12\n... 1//0\n... except ZeroDivisionError:\n... yield 666\n... except:\n... try:\n... x = 12\n... finally:\n... yield 12\n... except:\n... return\n>>> list(f())\n[12, 666]\n\n>>> def f():\n... yield\nTraceback (most recent call last):\nSyntaxError: invalid syntax\n\n>>> def f():\n... if 0:\n... yield\nTraceback (most recent call last):\nSyntaxError: invalid syntax\n\n>>> def f():\n... if 0:\n... yield 1\n>>> type(f())\n<type \'generator\'>\n\n>>> def f():\n... if "":\n... yield None\n>>> type(f())\n<type \'generator\'>\n\n>>> def f():\n... return\n... try:\n... if x==4:\n... pass\n... elif 0:\n... try:\n... 1//0\n... except SyntaxError:\n... pass\n... else:\n... if 0:\n... while 12:\n... x += 1\n... yield 2 # don\'t blink\n... f(a, b, c, d, e)\n... else:\n... pass\n... except:\n... x = 1\n... return\n>>> type(f())\n<type \'generator\'>\n\n>>> def f():\n... if 0:\n... def g():\n... yield 1\n...\n>>> type(f())\n<type \'NoneType\'>\n\n>>> def f():\n... if 0:\n... class C:\n... def __init__(self):\n... yield 1\n... def f(self):\n... yield 2\n>>> type(f())\n<type \'NoneType\'>\n\n>>> def f():\n... if 0:\n... return\n... if 0:\n... yield 2\n>>> type(f())\n<type \'generator\'>\n\n\n>>> def f():\n... if 0:\n... lambda x: x # shouldn\'t trigger here\n... return # or here\n... def f(i):\n... return 2*i # or here\n... if 0:\n... return 3 # but *this* sucks (line 8)\n... if 0:\n... yield 2 # because it\'s a generator\nTraceback (most recent call last):\nSyntaxError: \'return\' with argument inside generator (<doctest test.test_generators.__test__.syntax[22]>, line 8)\n\nThis one caused a crash (see SF bug 567538):\n\n>>> def f():\n... for i in range(3):\n... try:\n... continue\n... finally:\n... yield i\n...\n>>> g = f()\n>>> print g.next()\n0\n>>> print g.next()\n1\n>>> print g.next()\n2\n>>> print g.next()\nTraceback (most recent call last):\nStopIteration\n'
def conjoin(gs):
values = [
None] * len(gs)
def gen(i, values = values):
if i >= len(gs):
yield values
else:
for None in gs[i]():
values[i] = None
for x in gen(i + 1):
yield x
for x in gen(0):
yield x
def conjoin(gs):
n = len(gs)
values = [
None] * n
def gen(i, values = values):
if i >= n:
yield values
elif (n - i) % 3:
ip1 = i + 1
for None in gs[i]():
values[i] = None
for x in gen(ip1):
yield x
else:
for x in _gen3(i):
yield x
def _gen3(i, values = values):
if not i < n or (n - i) % 3 == 0:
raise AssertionError
ip1 = i + 1
ip2 = i + 2
ip3 = i + 3
(g, g1, g2) = gs[i:ip3]
if ip3 >= n:
for None in g():
values[i] = None
for None in g1():
values[ip1] = None
for None in g2():
values[ip2] = None
yield values
else:
for None in g():
values[i] = None
for None in g1():
values[ip1] = None
for None in g2():
values[ip2] = None
for x in _gen3(ip3):
yield x
for x in gen(0):
yield x
def flat_conjoin(gs):
n = len(gs)
values = [
None] * n
iters = [
None] * n
_StopIteration = StopIteration
i = 0
while None:
try:
while i < n:
it = iters[i] = gs[i]().next
values[i] = it()
i += 1
except _StopIteration:
pass
if not i == n:
raise AssertionError
yield values
i -= 1
while i >= 0:
try:
values[i] = iters[i]()
i += 1
continue
except _StopIteration:
i -= 1
continue
None<EXCEPTION MATCH>_StopIteration
if not i < 0:
raise AssertionError
break
class Queens:
def __init__(self, n):
self.n = n
rangen = range(n)
self.rowgenerators = []
for i in rangen:
rowuses = [ 0x1L << j | 0x1L << (n + i - j) + n - 1 | 0x1L << (n + 2 * n - 1) + i + j for j in rangen ]
conjoin_tests = '\n\nGenerate the 3-bit binary numbers in order. This illustrates dumbest-\npossible use of conjoin, just to generate the full cross-product.\n\n>>> for c in conjoin([lambda: iter((0, 1))] * 3):\n... print c\n[0, 0, 0]\n[0, 0, 1]\n[0, 1, 0]\n[0, 1, 1]\n[1, 0, 0]\n[1, 0, 1]\n[1, 1, 0]\n[1, 1, 1]\n\nFor efficiency in typical backtracking apps, conjoin() yields the same list\nobject each time. So if you want to save away a full account of its\ngenerated sequence, you need to copy its results.\n\n>>> def gencopy(iterator):\n... for x in iterator:\n... yield x[:]\n\n>>> for n in range(10):\n... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))\n... print n, len(all), all[0] == [0] * n, all[-1] == [1] * n\n0 1 True True\n1 2 True True\n2 4 True True\n3 8 True True\n4 16 True True\n5 32 True True\n6 64 True True\n7 128 True True\n8 256 True True\n9 512 True True\n\nAnd run an 8-queens solver.\n\n>>> q = Queens(8)\n>>> LIMIT = 2\n>>> count = 0\n>>> for row2col in q.solve():\n... count += 1\n... if count <= LIMIT:\n... print "Solution", count\n... q.printsolution(row2col)\nSolution 1\n+-+-+-+-+-+-+-+-+\n|Q| | | | | | | |\n+-+-+-+-+-+-+-+-+\n| | | | |Q| | | |\n+-+-+-+-+-+-+-+-+\n| | | | | | | |Q|\n+-+-+-+-+-+-+-+-+\n| | | | | |Q| | |\n+-+-+-+-+-+-+-+-+\n| | |Q| | | | | |\n+-+-+-+-+-+-+-+-+\n| | | | | | |Q| |\n+-+-+-+-+-+-+-+-+\n| |Q| | | | | | |\n+-+-+-+-+-+-+-+-+\n| | | |Q| | | | |\n+-+-+-+-+-+-+-+-+\nSolution 2\n+-+-+-+-+-+-+-+-+\n|Q| | | | | | | |\n+-+-+-+-+-+-+-+-+\n| | | | | |Q| | |\n+-+-+-+-+-+-+-+-+\n| | | | | | | |Q|\n+-+-+-+-+-+-+-+-+\n| | |Q| | | | | |\n+-+-+-+-+-+-+-+-+\n| | | | | | |Q| |\n+-+-+-+-+-+-+-+-+\n| | | |Q| | | | |\n+-+-+-+-+-+-+-+-+\n| |Q| | | | | | |\n+-+-+-+-+-+-+-+-+\n| | | | |Q| | | |\n+-+-+-+-+-+-+-+-+\n\n>>> print count, "solutions in all."\n92 solutions in all.\n\nAnd run a Knight\'s Tour on a 10x10 board. Note that there are about\n20,000 solutions even on a 6x6 board, so don\'t dare run this to exhaustion.\n\n>>> k = Knights(10, 10)\n>>> LIMIT = 2\n>>> count = 0\n>>> for x in k.solve():\n... count += 1\n... if count <= LIMIT:\n... print "Solution", count\n... k.printsolution(x)\n... else:\n... break\nSolution 1\n+---+---+---+---+---+---+---+---+---+---+\n| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|\n+---+---+---+---+---+---+---+---+---+---+\n| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|\n+---+---+---+---+---+---+---+---+---+---+\n| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|\n+---+---+---+---+---+---+---+---+---+---+\n| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|\n+---+---+---+---+---+---+---+---+---+---+\n| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|\n+---+---+---+---+---+---+---+---+---+---+\n| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|\n+---+---+---+---+---+---+---+---+---+---+\n| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|\n+---+---+---+---+---+---+---+---+---+---+\n| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|\n+---+---+---+---+---+---+---+---+---+---+\n| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|\n+---+---+---+---+---+---+---+---+---+---+\n| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|\n+---+---+---+---+---+---+---+---+---+---+\nSolution 2\n+---+---+---+---+---+---+---+---+---+---+\n| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|\n+---+---+---+---+---+---+---+---+---+---+\n| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|\n+---+---+---+---+---+---+---+---+---+---+\n| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|\n+---+---+---+---+---+---+---+---+---+---+\n| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|\n+---+---+---+---+---+---+---+---+---+---+\n| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|\n+---+---+---+---+---+---+---+---+---+---+\n| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|\n+---+---+---+---+---+---+---+---+---+---+\n| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|\n+---+---+---+---+---+---+---+---+---+---+\n| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|\n+---+---+---+---+---+---+---+---+---+---+\n| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|\n+---+---+---+---+---+---+---+---+---+---+\n| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|\n+---+---+---+---+---+---+---+---+---+---+\n'
weakref_tests = "Generators are weakly referencable:\n\n>>> import weakref\n>>> def gen():\n... yield 'foo!'\n...\n>>> wr = weakref.ref(gen)\n>>> wr() is gen\nTrue\n>>> p = weakref.proxy(gen)\n\nGenerator-iterators are weakly referencable as well:\n\n>>> gi = gen()\n>>> wr = weakref.ref(gi)\n>>> wr() is gi\nTrue\n>>> p = weakref.proxy(gi)\n>>> list(p)\n['foo!']\n\n"